/*
 * Copyright 2008 Carnegie Mellon University
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package edu.cmu.lti.sepia.task.conversion;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Converter between trec_eval result and aclia ir4qa format.
 * @author Hideki Shima
 *
 */
public class TrecFormatConverter {

	/**
	 * Generates XML from TREC Format
	 * 
	 * Details about ACLIA IR4QA XML format:
	 * http://aclia.lti.cs.cmu.edu/wiki/SubmissionFormat
	 * 
	 * Details about TREC format:
	 * http://trec.nist.gov/trec_eval/trec_eval_latest.tar.gz
	 * http://www.ir.iit.edu/~dagr/cs529/files/project_files/trec_eval_desc.htm
	 * 
	 * 
	 * Sample input: 
	 * 301	Q0	FBIS4-46846	96	  2.144021	STANDARD
	 * 303	Q0	FT941-793	96	  1.901362	STANDARD
	 * 301	Q0	FT943-2588	95	  2.150375	STANDARD
	 */
	public static String generateXMLFromTrec( String trecFormat ) {
		Map<String,List<Doc>> docs = new LinkedHashMap<String,List<Doc>>();
		String[] lines = trecFormat.split("\n");
		String runid = null;
		for ( String line : lines ) {
			String[] elements = line.split("\\s+");
			if ( elements.length < 6 ) continue;
			if ( runid == null ) runid = elements[5];
			Doc doc = new Doc( elements[2], elements[4] );
			String topicId = elements[0];
			List<Doc> docList = (docs.get(topicId)!=null)?docs.get(topicId):new ArrayList<Doc>();
			docList.add( doc );
			docs.put(topicId, docList);
		}
		
		StringBuilder result = new StringBuilder();
		result.append( "<TOPIC_SET>\n" );
		result.append( "  <METADATA>\n" );
		result.append( "    <RUNID>"+runid+"</RUNID>\n" );
		result.append( "    <DESCRIPTION><![CDATA[ *** Fill in details of your system here *** ]]></DESCRIPTION>\n" );
		result.append( "  </METADATA>\n" );
		for ( Entry<String,List<Doc>> entry : docs.entrySet() ) {
			result.append( toXML( entry.getKey(), entry.getValue() ) );
		}
		result.append( "</TOPIC_SET>\n" );
		
		return result.toString();
	}
	
	/**
	 * Expected output from this method:
	 * <code><pre>
	 *   <TOPIC ID="ACLIA1-JA-T1">
	 * 	    <IR4QA_RESULT>
	 * 	      <DOCUMENT RANK="1" DOCID="JA-010101032" SCORE="1.00" />
	 * 	      <DOCUMENT RANK="2" DOCID="JA-001116222" SCORE="0.92" />
	 * 	      <DOCUMENT RANK="3" DOCID="JA-001110059" SCORE="0.91" />
	 * 	      <DOCUMENT RANK="4" DOCID="JA-990825062" SCORE="0.91" />
	 * 	    </IR4QA_RESULT>
	 * 	  </TOPIC>
	 * </pre></code>
	 * @return partial xml
	 */
	private static String toXML( String topicId, List<Doc> docs ) {
		Collections.sort(docs);
		StringBuilder sb = new StringBuilder();
		sb.append( "  <TOPIC ID=\""+topicId+"\">\n" );
		sb.append( "    <IR4QA_RESULT>\n" );
		for ( int i=0; i<docs.size(); i++ ) {
			Doc doc = docs.get(i);
			sb.append( "      <DOCUMENT RANK=\""+(i+1)+"\" ");
			sb.append( "DOCID=\""+doc.docid+"\" " );
			sb.append( "SCORE=\""+doc.score+"\" />\n" );
		}
		sb.append( "    </IR4QA_RESULT>\n" );
		sb.append( "  </TOPIC>\n" );
		return sb.toString();
	}
	
	public void generateTrecFormatFromXML( String xml ) {
		//TODO: implement this method later
	}
	
	public static void main(String[] args) {
		// Already tested with sample result files contained in trec_eval 8.1.
		
		//String trecResult = FileUtil.readFile("J:/trec_eval.8.1/test/results.test");
		//System.out.println( TrecFormatConverter.generateXMLFromTrec( trecResult ) );
	}
	
}

/**
 * Temporal document representation that is sortable
 * @author Hideki Shima
 *
 */
class Doc implements Comparable<Doc> {
  public String docid;
  public String score; // intentionally keep original string, rather than making it into a double
  public Doc( String docid, String score ) {
    this.docid = docid;
    this.score = score;
  }
  
  public int compareTo( Doc doc ) {
    double d1 = Double.parseDouble( this.score );
    double d2 = Double.parseDouble( doc.score );
    if (d1 < d2) {
      return 1;
    } else if (d1 > d2) {
      return -1;
    } else {
      return 0;
    }
  }
}